package com.zxl.live.tools.tools;

import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.os.Build;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 进程相关处理
 * Created by Administrator on 2015/9/15.
 */
public class ProcessUtils {

    /** first app user */
    public static final int AID_APP = 10000;

    /** offset for uid ranges for each user */
    public static final int AID_USER = 100000;


    private static FilenameFilter sFilenameFilter = new FilenameFilter() {

        /**
         * 匹配模式，只要数字
         */
        private Pattern mPattern = Pattern.compile("^[0-9]+$");

        @Override
        public boolean accept(File dir, String filename) {
            return mPattern.matcher(filename).matches();
        }
    };

    public static String getForegroundApp(Context context) {
        File[] files = new File("/proc").listFiles(sFilenameFilter);
        int lowestOomScore = Integer.MAX_VALUE;
//        String foregroundProcess = null;

        int foregroundProcessUid = -1;

        for (File file : files) {
            if (!file.isDirectory()) {
                continue;
            }

            int pid;
            try {
                pid = Integer.parseInt(file.getName());
            } catch (NumberFormatException e) {
                continue;
            }

            try {
                String cgroup = read(String.format("/proc/%d/cgroup", pid));

                String[] lines = cgroup.split("\n");

                if (lines.length != 2) {
                    continue;
                }

                String cpuSubsystem = lines[0];
                String cpuAcctSubsystem = lines[1];

                if (!cpuAcctSubsystem.endsWith(Integer.toString(pid))) {
                    // not an application process
                    continue;
                }

                if (cpuSubsystem.endsWith("bg_non_interactive")) {
                    // background policy
                    continue;
                }

//                String cmdline = read(String.format("/proc/%d/cmdline", pid));
//
//                if (cmdline.contains("com.android.systemui")) {
//                    continue;
//                }

                int uid = Integer.parseInt(cpuAcctSubsystem.split(":")[2].split("/")[1].replace("uid_", ""));
                if (uid >= 1000 && uid <= 1038) {
                    // system process
                    continue;
                }

                int appId = uid - AID_APP;
//                int userId = 0;
                // loop until we get the correct user id.
                // 100000 is the offset for each user.
                while (appId > AID_USER) {
                    appId -= AID_USER;
//                    userId++;
                }

                if (appId < 0) {
                    continue;
                }

                // u{user_id}_a{app_id} is used on API 17+ for multiple user account support.
                // String uidName = String.format("u%d_a%d", userId, appId);

                File oomScoreAdj = new File(String.format("/proc/%d/oom_score_adj", pid));
                if (oomScoreAdj.canRead()) {
                    int oomAdj = Integer.parseInt(read(oomScoreAdj.getAbsolutePath()));
                    if (oomAdj != 0) {
                        continue;
                    }
                }

                int oomScore = Integer.parseInt(read(String.format("/proc/%d/oom_score", pid)));
                if (oomScore < lowestOomScore) {
                    lowestOomScore = oomScore;
//                    foregroundProcess = cmdline;
                    foregroundProcessUid = uid;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (foregroundProcessUid != -1) {
            return context.getPackageManager().getPackagesForUid(foregroundProcessUid)[0];
        }
        return "";
    }

    private static String read(String path) throws IOException {
        StringBuilder output = new StringBuilder();
        BufferedReader reader = new BufferedReader(new FileReader(path));
        output.append(reader.readLine());
        for (String line = reader.readLine(); line != null; line = reader.readLine()) {
            output.append('\n').append(line);
        }
        reader.close();
        return output.toString();
    }


    private static long sPreviousTimeStp = 0;

    private static final long QUARTER = 15 * 60 * 1000;

    /**
     * 用户是否需要开启UsageStats
     * @param context
     * @return
     */
    public static boolean needStartUsageStats(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
                UsageStatsManager usm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
                Calendar calendar = Calendar.getInstance();
                long endTime = calendar.getTimeInMillis();
                calendar.add(Calendar.YEAR, -1);
                long startTime = calendar.getTimeInMillis();
                List<UsageStats> usageStatsList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, startTime, endTime);
                return usageStatsList == null || usageStatsList.isEmpty();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    private static ComponentName getLauncherTopAppBelowLollipop(Context context) {
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> appTasks = activityManager.getRunningTasks(1);
        if (null != appTasks && !appTasks.isEmpty()) {
            return appTasks.get(0).topActivity;
        }
        return null;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static ComponentName getLauncherTopAppUpLollipop(Context context) {
        try {
            String packageName = "";
            String className = "";
            long endTime = System.currentTimeMillis();
            long beginTime = endTime - 10000;
            UsageStatsManager sUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
            UsageEvents.Event event = new UsageEvents.Event();
            UsageEvents usageEvents = sUsageStatsManager.queryEvents(beginTime, endTime);
            while (usageEvents.hasNextEvent()) {
                usageEvents.getNextEvent(event);
                if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
                    packageName = event.getPackageName();
                    className = event.getClassName();
                }
            }

            if (!android.text.TextUtils.isEmpty(packageName)) {
                return new ComponentName(packageName, className);
            }

            //辅助
            if (endTime - sPreviousTimeStp > QUARTER) {
                if (needStartUsageStats(context)) {
                    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
                        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
                        List<ActivityManager.RunningAppProcessInfo> pis = activityManager.getRunningAppProcesses();
                        for (ActivityManager.RunningAppProcessInfo pi : pis) {
                            if (pi.pkgList.length == 1) {
                                return new ComponentName(pi.pkgList[0], "");
                            }
                        }
                    }
                    return new ComponentName(getForegroundApp(context), "");
                } else {
                    sPreviousTimeStp = endTime;
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    //当前版本是否小于5.0
    private final static boolean IS_BELOW_LOLLIPOP = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? true : false;

    /**
     * 获取栈顶元素
     * @param context
     * @return
     */
    public static ComponentName getLauncherTopApp(Context context) {
        if (IS_BELOW_LOLLIPOP) {
            return getLauncherTopAppBelowLollipop(context);
        } else {
            return getLauncherTopAppUpLollipop(context);
        }
    }
}
